<script lang="ts" setup>
import {defineModel, onMounted, ref, watch} from 'vue'
import {IForm} from '@/interface/form'
import {ElMessage} from 'element-plus'
import {getDefaultValue} from '@/utils/utils.ts'
import BaseEditor from '@/components/BaseEditor/index.vue'
import BaseNumberRange from '@/components/BaseNumberRange/index.vue'
import BaseSimple from '@/components/BaseSimple/index.vue'

defineOptions({
	name: 'BaseForm'
})

const prop = defineProps<{
	formConfig: IForm
}>()

const model = defineModel<any>() // 双向绑定
const rules = ref({})
const formRef = ref()

onMounted(() => {
	createRulesRequired()
})
watch(() => prop.formConfig.config, (val) => {
	model.value = getDefaultValue(val, model.value)
}, {
	deep: true,
	immediate: true
})
const createRulesRequired = () => {
	const obj = {}
	prop.formConfig.config.map((res) => {
		if (res.bind) {
			const arr: any[] = res.required ? [{}] : []
			if (res.required && res.trigger) {
				arr[0].trigger = res.trigger
				arr[0].required = true
				arr[0].message = res.required
			}
			obj[res.bind] = arr
		}

		if (res.rules) {
			obj[res.bind] = obj[res.bind].concat(res.rules)
		}
	})
	rules.value = obj
}

const validate = async () => {
	let flag: any = false
	let valid = await formRef.value.validate().catch((obj: any) => {
		let str = ''
		for (const key in obj) {
			if (str === '') {
				str += '请检查以下信息：' + obj[key][0].message
			} else {
				str += '、' + obj[key][0].message
			}
		}
		ElMessage.warning(str)
	})
	if (valid === true) {
		flag = model.value
	}
	return flag
}
const resetFields = () => {
	formRef.value.resetFields()
}

const validateField = (filed: string, fn: Function) => {
	formRef.value.validateField(filed, fn)
}
defineExpose({validate, resetFields, validateField})
</script>

<template>
	<el-form
		ref="formRef"
		:model="model"
		:rules="rules"
		:validate-on-rule-change="false"
		inline
		label-position="right"
		label-width="auto"
		size="small"
		status-icon
		v-bind="formConfig.otherConfig?.formConfig"
	>
		<template v-for="item in formConfig.config" :key="item.bind">
			<el-form-item
				v-if="!item.isHide && (item.showHide ? item.showHide(item) : true)"
				:class="['col-' + (item.col ? item.col : 12), 'relative']"
				:label="item.name"
				:prop="item.bind"
				:style="'padding-left:' + (formConfig.otherConfig?.labelWidth || '120px')+';' + 'box-sizing: border-box;'"
				v-bind="formConfig.otherConfig?.formItemConfig"
			>
				<template v-if="item.needToolTip" #label="{label}">
					<div>
						<el-tooltip :content="item.needToolTip.content" :placement="item.needToolTip.placement||'top'">
							<BaseIcon
								:color="item.needToolTip.color"
								:icon="item.needToolTip.icon||'QuestionFilled'"
								:size="item.needToolTip.size||12"
							/>
						</el-tooltip>
						{{ label }}
					</div>
				</template>
				<slot v-if="item.component === 'customSlot'" :name="item.bind"/>
				<el-select
					v-else-if="item.component === 'ElSelect' || item.component === 'el-select'"
					v-model="model[item.bind]"
					v-bind="item.attr"
					v-on="item.methods || {}"
				>
					<el-option
						v-for="el in item.dictList"
						:key="el[item.dictProps?.value || 'value']"
						:label="el[item.dictProps?.label || 'label']"
						:value="el[item.dictProps?.value || 'value']"
					/>
				</el-select>
				<el-checkbox-group
					v-else-if="item.component === 'ElCheckboxGroup' || item.component === 'el-checkbox-group'"
					v-model="model[item.bind]"
					v-bind="item.attr"
					v-on="item.methods || {}"
				>
					<el-checkbox
						v-for="el in item.dictList"
						:key="el[item.dictProps?.value || 'value']"
						:disabled="el.disabled"
						:value="el[item.dictProps?.value || 'value']"
						v-bind="item.attr"
					>
						{{ el[item.dictProps?.label || 'label'] }}
					</el-checkbox>
				</el-checkbox-group>
				<el-radio-group
					v-else-if="item.component === 'ElRadioGroup' || item.component === 'el-radio-group'"
					v-model="model[item.bind]"
					v-bind="item.attr"
					v-on="item.methods || {}"
				>
					<el-radio
						v-for="el in item.dictList"
						:key="el[item.dictProps?.value || 'value']"
						:disabled="el.disabled"
						:value="el[item.dictProps?.value || 'value']"
						v-bind="item.attr"
					>
						{{ el[item.dictProps?.label || 'label'] }}
					</el-radio>
				</el-radio-group>
				<BaseEditor
					v-else-if="item.component === 'Editor'"
					v-model="model[item.bind]"
					v-bind="item.attr"
				/>
				<div v-else-if="item.component === 'HTML'" style="min-height: 24px;">{{ model[item.bind] }}</div>
				<BaseNumberRange
					v-else-if="item.component === 'NumberRange'"
					v-model="model[item.bind]"
					:max-range="item.attr?.['maxRange']"
					:min-range="item.attr?.['minRange']"
				/>
				<BaseSimple
					v-else-if="item.component === 'SimpleUpload'"
					v-model="model[item.bind]"
					:accept="item.attr?.['accept']"
					:file-size="item.attr?.['fileSize']"
					:file-type="item.attr?.['fileType']"
					:limit="item.attr?.['limit']"
					:multiple="item.attr?.['multiple']"
				/>
				<component
					:is="item.component"
					v-else
					v-model="model[item.bind]"
					v-bind="item.attr"
					v-on="item.methods || {}"
				/>
			</el-form-item>
		</template>
	</el-form>
</template>

<style lang="scss" scoped>
.col-24 {
	width: 100%;
}

.col-12 {
	width: 50%;
}

.col-7 {
	width: 33.3%;
}

.col-6 {
	width: 25%;
}

.col-4 {
	width: 20%;
}

:deep(.el-form-item__content) {
	width: 100%;
	position: relative;
}

:deep(.el-input),
:deep(.el-select),
:deep(.el-date-editor),
:deep(.el-cascader) {
	width: 100%;
}

.el-form--inline :deep(.el-form-item) {
	margin-right: 0;
	padding-right: 10px;
}

:deep(.el-form-item__label-wrap) {
	position: absolute;
	top: 0;
	left: 0;
}

:deep(.el-form-item__label) {
	min-height: 20px;
}
</style>
